
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>ForkJoinPool高效处理异步任务 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>ForkJoinPool高效处理异步任务 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">ForkJoinPool 被设计用来解决传统线程池在处理何种特定问题时遇到的性能瓶颈？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">ForkJoinPool 旨在解决传统线程池在处理大量小任务并发执行，特别是“大任务拆分成小任务”的场景时，因频繁的线程创建与销毁导致的性能瓶颈和系统开销。</div>
          </div>
          <div class="card-source">来源: 1.1 ForkJoinPool的背景</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">什么是“工作窃取算法”，它是如何提高 ForkJoinPool 效率的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">工作窃取算法（Work Stealing）是 ForkJoinPool 的核心思想。它允许某个完成自己任务的线程从其他线程的任务队列中“窃取”任务来执行，这样可以避免线程空闲等待，减少线程切换开销，从而提高整体执行效率和资源利用率。</div>
          </div>
          <div class="card-source">来源: 1.1 ForkJoinPool的背景</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">ForkJoinPool 的标准工作流程包含哪三个主要步骤？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">其工作流程主要包括三个步骤：1. 任务拆分（通过 fork() 方法将大任务拆分为小任务）；2. 并行执行（利用多核CPU同时处理小任务）；3. 工作窃取（空闲线程从其他线程队列窃取任务来执行）。</div>
          </div>
          <div class="card-source">来源: 1.2 ForkJoinPool的工作机制</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">相比传统的 ExecutorService 线程池，ForkJoinPool 有哪些显著的优势？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">ForkJoinPool 的主要优势有三点：1. 高效的任务拆分与合并，特别适合递归计算任务；2. 拥有工作窃取机制，避免线程资源浪费；3. 能够减少线程切换的开销，提高并发执行效率。</div>
          </div>
          <div class="card-source">来源: 2.2 ForkJoinPool的优势</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在 ForkJoinPool 中执行的任务需要继承自哪个基类？它主要分为哪两种具体实现，它们之间有何区别？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在 ForkJoinPool 中执行的任务是 ForkJoinTask 的子类。它主要分为两种类型：RecursiveTask 用于有返回值的任务，而 RecursiveAction 用于无返回值的任务。</div>
          </div>
          <div class="card-source">来源: 3.2 ForkJoinTask的使用</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在编写 ForkJoinTask 时，fork() 和 join() 方法的核心作用分别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">fork() 方法用于将子任务提交给 ForkJoinPool 进行异步执行。join() 方法则会阻塞当前线程，直到对应的子任务执行完成，并返回其计算结果（对于 RecursiveTask）。</div>
          </div>
          <div class="card-source">来源: 3.2.1 RecursiveTask示例</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">请具体描述 ForkJoinPool 的工作窃取机制是如何利用双端队列（Deque）运作的。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在 ForkJoinPool 中，每个线程都有一个自己的双端队列（Deque）来管理任务。当线程执行任务时，它会从自己的队列中弹出任务。如果队列为空，它会尝试从其他线程队列的尾部窃取一个任务来执行，从而最大化地利用CPU核心。</div>
          </div>
          <div class="card-source">来源: 4. ForkJoinPool的工作窃取机制</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">ForkJoinPool 是如何通过任务处理方式来减少线程切换开销的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">ForkJoinPool 通过任务拆分与合并的机制，减少了线程间的竞争和切换。一个线程可以处理一个大任务分解出的多个子任务，而不是频繁地切换去处理完全不相关的任务，从而降低了上下文切换的开销。</div>
          </div>
          <div class="card-source">来源: 5. ForkJoinPool的性能优势</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在Java中，有哪些常见的方式可以创建一个 ForkJoinPool 实例？如果创建时不指定线程数，其默认大小通常是多少？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以通过其构造方法 `new ForkJoinPool(int parallelism)` 来创建一个指定线程数的池，或者通过静态方法 `ForkJoinPool.commonPool()` 来获取一个系统公共的线程池。如果不指定线程池大小，默认大小通常是CPU的核心数。</div>
          </div>
          <div class="card-source">来源: 3.1 ForkJoinPool的基本创建</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
